inspector: Fix teardown of the general tab
authorMatthias Clasen <mclasen@redhat.com>
Sun, 6 Sep 2020 02:35:30 +0000 (22:35 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sun, 6 Sep 2020 02:35:30 +0000 (22:35 -0400)
We were connecting signal handlers to the display
and seats here, and never cleaning them up, leading
to crashes after the inspector is closed. This is
fairly easy to reproduce under Wayland, where the
scroll device is only created the first time we
create a scroll event.

gtk/inspector/general.c

index 76bd0011e2d27ac522df300d68471000bcd1f9a6..ab368e2f8da058a1bcd8eac98e78d95c0a378f64 100644 (file)
@@ -817,6 +817,13 @@ add_seat (GtkInspectorGeneral *gen,
   g_list_free (list);
 }
 
+static void
+disconnect_seat (GtkInspectorGeneral *gen,
+                 GdkSeat             *seat)
+{
+  g_signal_handlers_disconnect_by_func (seat, G_CALLBACK (populate_seats), gen);
+}
+
 static void
 populate_seats (GtkInspectorGeneral *gen)
 {
@@ -835,11 +842,28 @@ populate_seats (GtkInspectorGeneral *gen)
   g_list_free (list);
 }
 
+static void
+seat_added (GdkDisplay          *display,
+            GdkSeat             *seat,
+            GtkInspectorGeneral *gen)
+{
+  populate_seats (gen);
+}
+
+static void
+seat_removed (GdkDisplay          *display,
+              GdkSeat             *seat,
+              GtkInspectorGeneral *gen)
+{
+  disconnect_seat (gen, seat);
+  populate_seats (gen);
+}
+
 static void
 init_device (GtkInspectorGeneral *gen)
 {
-  g_signal_connect_swapped (gen->display, "seat-added", G_CALLBACK (populate_seats), gen);
-  g_signal_connect_swapped (gen->display, "seat-removed", G_CALLBACK (populate_seats), gen);
+  g_signal_connect (gen->display, "seat-added", G_CALLBACK (seat_added), gen);
+  g_signal_connect (gen->display, "seat-removed", G_CALLBACK (seat_removed), gen);
 
   populate_seats (gen);
 }
@@ -911,9 +935,18 @@ static void
 gtk_inspector_general_dispose (GObject *object)
 {
   GtkInspectorGeneral *gen = GTK_INSPECTOR_GENERAL (object);
+  GList *list, *l;
 
   g_clear_pointer (&gen->swin, gtk_widget_unparent);
 
+  g_signal_handlers_disconnect_by_func (gen->display, G_CALLBACK (seat_added), gen);
+  g_signal_handlers_disconnect_by_func (gen->display, G_CALLBACK (seat_removed), gen);
+
+  list = gdk_display_list_seats (gen->display);
+  for (l = list; l; l = l->next)
+    disconnect_seat (gen, GDK_SEAT (l->data));
+  g_list_free (list);
+
   G_OBJECT_CLASS (gtk_inspector_general_parent_class)->dispose (object);
 }